﻿#include"GameModel.h"
#include<time.h>
#include<stdlib.h>
#include<QDebug>

void GameModel::startGame(GameType type){
    gameType=type;
    //初始化棋盘
    gameMapVec.clear();
    for(int i=0;i<BOARD_GRAD_SIZE;i++){
        std::vector<int>lineBoard;
        for(int j=0;j<BOARD_GRAD_SIZE;j++)
            lineBoard.push_back(0);
        gameMapVec.push_back(lineBoard);
    }
    //如果是AI模式，需要初始化评分数组
    if(gameType==AI){
        scoreMapVec.clear();
        for(int i=0;i<BOARD_GRAD_SIZE;i++){
            std::vector<int>lineScores;
            for(int j=0;j<BOARD_GRAD_SIZE;j++)
                lineScores.push_back(0);
            scoreMapVec.push_back(lineScores);

        }

    }
    //轮到黑方下棋为true，白方为false
    playerFlag=true;
}
void GameModel::actionByPerson(int row, int col){
    updateGameMap(row,col);
}
void GameModel::updateGameMap(int row, int col){
    if(playerFlag)
        gameMapVec[row][col]=1;
    else
        gameMapVec[row][col]=-1;
    //换手
    playerFlag=!playerFlag;


}
bool GameModel::isWIn(int row, int col){
    //横竖斜左斜右，每种情况都根据当前落子往后遍历五个棋子，有一种符合就算赢
    //水平
    //当前位置往右判断4个 然后往左移动四格 在移动的同时，以移动后的位置一直往右判断四格
   //20种情况
    for(int i=0;i<5;i++){
        if(col-i>0&&
                col-i+4<BOARD_GRAD_SIZE&&
                gameMapVec[row][col-i]==gameMapVec[row][col-i+1]&&
                gameMapVec[row][col-i]==gameMapVec[row][col-i+2]&&
                gameMapVec[row][col-i]==gameMapVec[row][col-i+3]&&
                gameMapVec[row][col-i]==gameMapVec[row][col-i+4])
            return true;
    }
    //竖直
    for(int i=0;i<5;i++){
        if(row-i>0&&
                row-i+4<BOARD_GRAD_SIZE&&

                gameMapVec[row-i][col]==gameMapVec[row-i+1][col]&&
                gameMapVec[row-i][col]==gameMapVec[row-i+2][col]&&
                gameMapVec[row-i][col]==gameMapVec[row-i+3][col]&&
                gameMapVec[row-i][col]==gameMapVec[row-i+4][col])
            return true;
    }
    // '/'方向       乐
    for(int i=0;i<5;i++){
         if(row+i<BOARD_GRAD_SIZE&&
                  row+i-4>0&&
                  col-i>0&&
                  col-i+4<BOARD_GRAD_SIZE&&
                gameMapVec[row+i][col-i]==gameMapVec[row+i-1][col-i+1]&&
                gameMapVec[row+i][col-i]==gameMapVec[row+i-2][col-i+2]&&
                gameMapVec[row+i][col-i]==gameMapVec[row+i-3][col-i+3]&&
                gameMapVec[row+i][col-i]==gameMapVec[row+i-4][col-i+4])
            return true;
    }
    //'\'方向
    for(int i=0;i<5;i++){
         if(row-i+4<BOARD_GRAD_SIZE&&
                  row-i>0&&
                  col-i>0&&
                  col-i+4<BOARD_GRAD_SIZE&&
                gameMapVec[row-i][col-i]==gameMapVec[row-i+1][col-i+1]&&
                gameMapVec[row-i][col-i]==gameMapVec[row-i+2][col-i+2]&&
                gameMapVec[row-i][col-i]==gameMapVec[row-i+3][col-i+3]&&
                gameMapVec[row-i][col-i]==gameMapVec[row-i+4][col-i+4])
            return true;
    }
    return false;
}

//AI下棋评分函数，某一点的评分为多少，取评分最大的点下
void GameModel::calculateScore(){
    //统计玩家或者电脑炼成的子
    int personNum=0;//玩家连成的子个数
    int botNum=0;//AI连成子的个数
    int emptyNum=0;//各方向空白位的个数
    //清空评分数组
    scoreMapVec.clear();
    for(int i=0;i<BOARD_GRAD_SIZE;i++){
        std::vector<int>lineScores;
        for(int j=0;j<BOARD_GRAD_SIZE;j++)
            lineScores.push_back(0);
        scoreMapVec.push_back(lineScores);
        //计分(此处是完全遍历，可以用bfs或者dfs加减枝降低复杂度，通过调整权重值，调整AI智能)
        for(int row=0;row<BOARD_GRAD_SIZE;row++){
            for(int col=0;col<BOARD_GRAD_SIZE;col++){
                //空白点就计数
                if(row>0&&col>0&&
                        gameMapVec[row][col]==0){
                    //遍历周围八个方向
                    for(int y=-1;y<=1;y++){//-1 0 1
                        for(int x=-1;x<=1;x++){//-1 0 1
                            //重置
                            personNum=0;
                            botNum=0;
                            emptyNum=0;

                            //原坐标不算
                            if(!(y==0&&x==0)){
                                //八个方向 每个方向延伸四个子 从延伸的这些子中找到评分最高的点
                                //对玩家白子评分(正反两个方向)
                                for(int i=1;i<=4;i++){
                                    if(row+i*y>0&&row+i*y<BOARD_GRAD_SIZE&&
                                            col+i*x>0&&col+i*x<BOARD_GRAD_SIZE&&
                                            gameMapVec[row+i*y][col+i*x]==1){//真人落的子
                                        personNum++;
                                    }
                                    else if(row+i*y>0&&row+i*y<BOARD_GRAD_SIZE&&
                                            col+i*x>0&&col+i*x<BOARD_GRAD_SIZE&&
                                            gameMapVec[row+i*y][col+i*x]==0){//没下子的位置
                                        emptyNum++;
                                        break;
                                    }
                                    else//否则出边界
                                          break;
                                }

                                for(int i=1;i<=4;i++){
                                    if(row-i*y>0&&row-i*y<BOARD_GRAD_SIZE&&
                                            col-i*x>0&&col-i*x<BOARD_GRAD_SIZE&&
                                            gameMapVec[row-i*y][col-i*x]==1){//真人落的子
                                        personNum++;
                                    }
                                    else if(row-i*y>0&&row-i*y<BOARD_GRAD_SIZE&&
                                            col-i*x>0&&col-i*x<BOARD_GRAD_SIZE&&
                                            gameMapVec[row-i*y][col-i*x]==0){//没下子的位置
                                        emptyNum++;
                                        break;
                                    }
                                    else//否则出边界 或者有AI自己的子
                                          break;
                                }
                                if(personNum==1)
                                    scoreMapVec[row][col]+=10;//杀2
                                else if(personNum==2){//杀3
                                    if(emptyNum==1)
                                        scoreMapVec[row][col]+=30;
                                    else if(emptyNum==2)
                                        scoreMapVec[row][col]+=40;
                                }
                                else if(personNum==3){//杀4
                                    //量变空位不一样，优先级不同
                                    if(emptyNum==1)
                                        scoreMapVec[row][col]+=60;
                                    else if(emptyNum==2)
                                        scoreMapVec[row][col]+=110;
                                }
                                else if(personNum==4){//杀5
                                    scoreMapVec[row][col]+=10100;//输了悲
                                }
                                emptyNum=0;
                                //对AI  白子评分
                                //正方向
                                for(int i=1;i<=4;i++){
                                    if(row+i*y>0&&row+i*y<BOARD_GRAD_SIZE&&
                                            col+i*x>0&&col+i*x<BOARD_GRAD_SIZE&&
                                            gameMapVec[row+i*y][col+i*x]==-1){//真人落的子
                                        botNum++;
                                    }
                                    else if(row+i*y>0&&row+i*y<BOARD_GRAD_SIZE&&
                                            col+i*x>0&&col+i*x<BOARD_GRAD_SIZE&&
                                            gameMapVec[row+i*y][col+i*x]==0){//没下子的位置
                                        emptyNum++;
                                        break;
                                    }
                                    else//否则出边界
                                          break;
                                }

                                //反方向
                                for(int i=1;i<=4;i++){
                                    if(row-i*y>0&&row-i*y<BOARD_GRAD_SIZE&&
                                            col-i*x>0&&col-i*x<BOARD_GRAD_SIZE&&
                                            gameMapVec[row-i*y][col-i*x]==-1){//AI落的子
                                        botNum++;
                                    }
                                    else if(row-i*y>0&&row-i*y<BOARD_GRAD_SIZE&&
                                            col-i*x>0&&col-i*x<BOARD_GRAD_SIZE&&
                                            gameMapVec[row-i*y][col-i*x]==0){//没下子的位置
                                        emptyNum++;
                                        break;
                                    }
                                    else//否则出边界 或者有AI自己的子
                                          break;
                                }
                                if(botNum==0)//正常下子
                                    scoreMapVec[row][col]+=0;
                                else if(botNum==1)
                                    scoreMapVec[row][col]+=10;//活二
                                else if(botNum==2){
                                    if(emptyNum==1)//死三
                                        scoreMapVec[row][col]+=25;
                                    else if(emptyNum==2)//活三
                                        scoreMapVec[row][col]+=50;
                                }
                                else if(botNum==3){
                                    //量变空位不一样，优先级不同
                                    if(emptyNum==1)//死四
                                        scoreMapVec[row][col]+=55;
                                    else if(emptyNum==2)//活四
                                        scoreMapVec[row][col]+=100;

                                }
                                else if(botNum>=4){
                                    scoreMapVec[row][col]+=20000;//活五，最高优先级 win力
                                }
                        }
                    }
                }
            }
        }

    }
}
}
void GameModel::actionByAI(int &clickRow, int &clickCol){
    //计算评分
    calculateScore();
    //从评分力找到最大分数的位置
    int maxScore=0;
    std::vector<std::pair<int,int>>maxPoints;
    for(int row=1;row<BOARD_GRAD_SIZE;row++){
        for(int col=1;col<BOARD_GRAD_SIZE ;col++){
            //前提这个坐标是空的
            if(gameMapVec[row][col]==0){
                if(scoreMapVec[row][col]>maxScore){//找最大的数和坐标
                    maxPoints.clear();
                    maxScore=scoreMapVec[row][col];
                    maxPoints.push_back(std::make_pair(row,col));
                }
                else if(scoreMapVec[row][col]==maxScore)//如果有多个最大值
                    maxPoints.push_back(std::make_pair(row,col));
            }
        }
    }
    //随机落子，如果有多个点的话
    srand((unsigned)time(0));
    int index=rand()%maxPoints.size();
    std::pair<int,int>pointPair=maxPoints.at(index);
    clickRow=pointPair.first;//记录落子点
    clickCol=pointPair.second;
    updateGameMap(clickRow,clickCol);
}

void GameModel::startGame2(){
    //初始化棋盘
    //一个正方形矩阵其中棋盘外的标记为-1 即用不到
    //棋盘内 有棋子的地方为1 无棋子的地方为0      -2为可下点
    gameMapVec.clear();
    for(int i=0;i<BOARD_GRAD_SIZE2;i++){
        std::vector<int>lineBoard;
        for(int j=0;j<BOARD_GRAD_SIZE2;j++){
            if(i==0||i==1||i==BOARD_GRAD_SIZE2-2||i==BOARD_GRAD_SIZE2-1){
                if(j==0||j==1||j==BOARD_GRAD_SIZE2-1||j==BOARD_GRAD_SIZE2-2)
                    lineBoard.push_back(-1);
            else
                    lineBoard.push_back(1);
            }
            else
                  lineBoard.push_back(1);
        }
        gameMapVec.push_back(lineBoard);
    }
    if(initialPieceY==-1&&initialPieceX==-1){
       initialPieceY=3;
       initialPieceX=3;
    }
    gameMapVec[initialPieceY][initialPieceX]=0;
}
void GameModel::actionByPerson2(int row, int col){
    updateGameMap2(row,col);
}
void GameModel::updateGameMap2(int row, int col){
        gameMapVec[row][col]=1;
}
void GameModel::findDropLocation(int row,int col){
    //要防止越界 越界会崩溃

    //左
    if(col-1>=0&&gameMapVec[row][col-1]==1&&col-2>=0&&gameMapVec[row][col-2]==0){gameMapVec[row][col-2]=-2;qDebug()<<"左方找到";};
    //右
    if(col+1<BOARD_GRAD_SIZE2&&gameMapVec[row][col+1]==1&&col+2<BOARD_GRAD_SIZE2&&gameMapVec[row][col+2]==0){gameMapVec[row][col+2]=-2;qDebug()<<"右方找到";};
    //上
    if(row-1>=0&&gameMapVec[row-1][col]==1&&row-2>=0&&gameMapVec[row-2][col]==0){gameMapVec[row-2][col]=-2;qDebug()<<"上方找到";};
    //下
    if(row+1<BOARD_GRAD_SIZE2&&gameMapVec[row+1][col]==1&&row+2<BOARD_GRAD_SIZE2&&gameMapVec[row+2][col]==0){gameMapVec[row+2][col]=-2;qDebug()<<"下方找到";};

}
void GameModel::treatPreLocate(int prerow, int precol,int row,int col){
    qDebug()<<prerow<<precol<<row<<col;
    gameMapVec[prerow][precol]=0;
    gameMapVec[prerow+(row-prerow)/2][precol+(col-precol)/2]=0;
    //左
    if(precol-1>0&&gameMapVec[prerow][precol-1]==1&&precol-2>=0&&gameMapVec[prerow][precol-2]==-2){gameMapVec[prerow][precol-2]=0;qDebug()<<"消除左边";}
    //右
    if(precol+1<BOARD_GRAD_SIZE2&&gameMapVec[prerow][precol+1]==1&&precol+2<BOARD_GRAD_SIZE2&&gameMapVec[prerow][precol+2]==-2){gameMapVec[prerow][precol+2]=0;qDebug()<<"消除右边";}
    //上
    if(prerow-1>0&&gameMapVec[prerow-1][precol]==1&&prerow-2>=0&&gameMapVec[prerow-2][precol]==-2){gameMapVec[prerow-2][precol]=0;qDebug()<<"消除上面";}
    //下
    if(prerow+1<BOARD_GRAD_SIZE2&&gameMapVec[prerow+1][precol]==1&&prerow+2<BOARD_GRAD_SIZE2&&gameMapVec[prerow+2][precol]==-2){gameMapVec[prerow+2][precol]=0;qDebug()<<"消除下面";}
}
bool GameModel::judgeWin(){
    //遍历到所有存在的棋子 false 还能下 true 游戏结束
    for(int i=0;i<BOARD_GRAD_SIZE2;i++){
        for(int j=0;j<BOARD_GRAD_SIZE2;j++){
            if(gameMapVec[i][j]==1){
                //四个方向找是否能下
                if((j-1>0&&gameMapVec[i][j-1]==1&&j-2>0&&gameMapVec[i][j-2]==0)||
                        (j-1>0&&gameMapVec[i][j-1]==1&&j-2>0&&gameMapVec[i][j-2]==-2)){qDebug()<<"还能下";return false;}
                //右
                if((j+1<BOARD_GRAD_SIZE2&&gameMapVec[i][j+1]==1&&j+2<BOARD_GRAD_SIZE2&&gameMapVec[i][j+2]==0)||
                        (j+1<BOARD_GRAD_SIZE2&&gameMapVec[i][j+1]==1&&j+2<BOARD_GRAD_SIZE2&&gameMapVec[i][j+2]==-2)){return false;qDebug()<<"还能下";}
                //上
                if((i-1>0&&gameMapVec[i-1][j]==1&&i-2>0&&gameMapVec[i-2][j]==0)||
                        (i-1>0&&gameMapVec[i-1][j]==1&&i-2>0&&gameMapVec[i-2][j]==-2)){return false;qDebug()<<"还能下";}
                //下
                if((i+1<BOARD_GRAD_SIZE2&&gameMapVec[i+1][j]==1&&i+2<BOARD_GRAD_SIZE2&&gameMapVec[i+2][j]==0)||
                        (i+1<BOARD_GRAD_SIZE2&&gameMapVec[i+1][j]==1&&i+2<BOARD_GRAD_SIZE2&&gameMapVec[i+2][j]==-2)){return false;qDebug()<<"还能下";}
            }
        }
    }
    qDebug()<<"游戏结束";
    return true;
}
void GameModel::sameLocate(int prerow,int precol){
    //左
    if(precol-1>0&&gameMapVec[prerow][precol-1]==1&&precol-2>=0&&gameMapVec[prerow][precol-2]==-2){gameMapVec[prerow][precol-2]=0;qDebug()<<"消除左边";}
    //右
    if(precol+1<BOARD_GRAD_SIZE2&&gameMapVec[prerow][precol+1]==1&&precol+2<BOARD_GRAD_SIZE2&&gameMapVec[prerow][precol+2]==-2){gameMapVec[prerow][precol+2]=0;qDebug()<<"消除右边";}
    //上
    if(prerow-1>0&&gameMapVec[prerow-1][precol]==1&&prerow-2>=0&&gameMapVec[prerow-2][precol]==-2){gameMapVec[prerow-2][precol]=0;qDebug()<<"消除上面";}
    //下
    if(prerow+1<BOARD_GRAD_SIZE2&&gameMapVec[prerow+1][precol]==1&&prerow+2<BOARD_GRAD_SIZE2&&gameMapVec[prerow+2][precol]==-2){gameMapVec[prerow+2][precol]=0;qDebug()<<"消除下面";}

}

int GameModel::finalResult(){
    int count=0;
    for(int i=0;i<BOARD_GRAD_SIZE2;i++){
        for(int j=0;j<BOARD_GRAD_SIZE2;j++){
            if(gameMapVec[i][j]==1){
                count++;
            }
        }
    }
    return count;
}
